
#include <Inklude/ikCThread.h>
#include <tbb/tbb_thread.h>

using namespace Inklude;


ikCThread::ikCThread()
{
	m_hThread = NULL;
}

ikCThread::~ikCThread()
{
    DestroyThread();
}

struct _ikcthread_internal_data
{
    std::shared_ptr<std::function<void()> > m_func;
};

static DWORD WINAPI __internal_func_for_run_thread_class_ik_thread_abcd_efg(LPVOID pCodeFragment)
{
    auto pCode = (_ikcthread_internal_data*)pCodeFragment;
    auto func = *(pCode->m_func);
    func();
    delete pCode;
    return 0;
    //reinterpret_cast<ikCThreadCodeFragment<void>*>(pCodeFragment)->Execute();
}

static DWORD WINAPI __internal_func_for_class_ik_thread_abcd_efg(LPVOID pCodeFragment)
{
    reinterpret_cast<ikCThreadCodeFragment<void>*>(pCodeFragment)->Execute();
    return 0;
}

bool ikCThread::Start()
{
    m_bRunning = true;
	m_hThread = CreateThread(NULL,
							 0,
							 __internal_func_for_class_ik_thread_abcd_efg,
							 reinterpret_cast<LPVOID>(m_pCodeFragment.get()),
							 0,
							 &m_threadId);

	return (NULL != m_hThread);
}

bool ikCThread::DestroyThread()
{
	bool _bResult = false;
	if (NULL != m_hThread)
	{
        m_pCodeFragment = NULL;
        TerminateThread(m_hThread, 0);
		_bResult = (TRUE == CloseHandle(m_hThread));
		m_hThread = NULL;
        m_bRunning = false;
	}
	return _bResult;
}

void ikCThread::RegisterCodeFragement(THREAD_LAMBDA_SHRD_PTR pCodeFragment)
{
    m_pCodeFragment = pCodeFragment;
}

HANDLE ikCThread::RunThread(std::shared_ptr<std::function<void()> > func)
{
    _ikcthread_internal_data* pData = new _ikcthread_internal_data;
    pData->m_func = func;
    
    DWORD _retVal;
    HANDLE hThread = CreateThread(NULL,
							 0,
							 __internal_func_for_run_thread_class_ik_thread_abcd_efg,
							 reinterpret_cast<LPVOID>(pData),
							 0,
							 &_retVal);

    return hThread;
}
